package cj.web.pay.weixin;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import cj.utils.MD5Security;
import cj.utils.ReturnUUID;

/**
 * 微信统一下单方法
 * @author Administrator
 *
 */
public class UnifiedOrder extends WXConfig{
	
	/**
	 * 调用统一下单接口获取prepay_id
	 * @param body		商品描述
	 * @param out_trade_no	商户订单号
	 * @param total_fee	总金额
	 * @param spbill_create_ip	终端IP
	 * @param notify_url	通知地址
	 * @param openid	用户标识
	 * @param attach	附加数据标识
	 * @return
	 * @throws Exception 
	 */
	public Map getPrepayId(String body,String out_trade_no,String total_fee,String spbill_create_ip,
			String notify_url,String openid,String attach) throws Exception
	{
		Map rep = new HashMap();
		//随机参数
		String nonce_str = ReturnUUID.getUUID();
		String timeStamp = create_timestamp();
		//调用返回签名
		String sign = returnSignMd5(APPID, MCH_ID, nonce_str, body, out_trade_no, FEE_TYPE,
				total_fee, spbill_create_ip, notify_url, TRADE_TYPE, openid, attach);
		
		String return_code="";
		String return_msg="";
		String prepay_id ="";
		String paySign = "";
		
		StringBuffer requestContent=returnRequestContent(body, out_trade_no, total_fee, 
				spbill_create_ip, notify_url, openid, nonce_str, sign ,attach);
		//请求远端微信Http接口
		try {
			byte[] xml = HttpsUtil.post(UNIFIEDORDERURL, requestContent.toString(), CHARSETUTF8);
			String strXml = new String(xml, CHARSETUTF8);
			Map resultMap = returnPrepayIdForXml(strXml);
			
			return_code = resultMap.get("return_code").toString();
			if(SUCCESS.equals(return_code)){
				prepay_id = resultMap.get("prepay_id").toString();
				
				
				//JSAPI paySign
				paySign = getJSAPIpaySign(APPID, nonce_str, prepay_id, SIGNTYPE,timeStamp);
			}else{
				return_msg = resultMap.get("return_msg").toString();
			}
			
		} catch (KeyManagementException | NoSuchAlgorithmException
				| IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		rep.put("return_code", return_code);
		rep.put("return_msg", return_msg);
		rep.put("timeStamp", timeStamp);
		rep.put("nonce_str", nonce_str);
		rep.put("paySign", paySign);
		rep.put("prepay_id", prepay_id);
		return rep;
	}
	
	/**
	 * 更具请求后的XML返回PrepayId
	 * @param requestContent
	 * @return
	 */
	private Map returnPrepayIdForXml(String requestContent)
	{
		Map rep = new HashMap();
		Document doc = Jsoup.parse(requestContent);
		//请求返回编码
		String return_code = doc.getElementsByTag("return_code").first().text();
		//请求返回信息
		String return_msg = doc.getElementsByTag("return_msg").first().text();
		
		if(SUCCESS.equals(return_code)){
			//结果返回编码
			String result_code = doc.getElementsByTag("result_code").first().text();
			if(SUCCESS.equals(result_code)){
				String prepay_id = doc.getElementsByTag("prepay_id").first().text();
				rep.put("return_code", SUCCESS);
				rep.put("prepay_id", prepay_id);
			}else{
				String err_code = doc.getElementsByTag("err_code").first().text();
				String err_code_des = doc.getElementsByTag("err_code_des").first().text();
				rep.put("return_code", FAIL);
				rep.put("return_msg", err_code);
			}
		}else{
			rep.put("return_code", FAIL);
			rep.put("return_msg", return_msg);
		}
		
		return rep;
	}
	
	/**
	 * 返回JSAPI 的 paySign
	 * @param appid
	 * @param mch_id
	 * @param nonce_str
	 * @param sign
	 * @param body
	 * @param out_trade_no
	 * @param fee_type
	 * @param total_fee
	 * @param spbill_create_ip
	 * @param notify_url
	 * @param trade_type
	 * @param openid
	 * @return
	 * @throws Exception
	 */
	private static String getJSAPIpaySign(String appId,String nonceStr,String prepay_id,String signType,String timeStamp) throws Exception
	{
		
		//step1-----拼接字符串，key value 形式
		appId="appId="+appId;
		timeStamp="timeStamp="+timeStamp;
		nonceStr="nonceStr="+nonceStr;
		prepay_id="package=prepay_id="+prepay_id;
		signType="signType="+signType;
		
		String[] arr = new String[] {appId, timeStamp, nonceStr,prepay_id,signType};
		//step2-----将参数进行字典排序
		Arrays.sort(arr);
		StringBuilder content = new StringBuilder();
		for (int i = 0; i < arr.length; i++) {
			content.append(arr[i]+"&");
		}
		//step3-----将 key=xxx 加入最末位
		String ss = content+"key="+KEY;
//		System.out.println("url----"+ss);
		//step4-----将拼接号的字符串，MD5加密32位
		String sign_md5 = MD5Security.md5(ss);
//		System.out.println("sign----"+sign_md5);
		return sign_md5.toUpperCase();
	}
	
	private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
	
	/**
	 * 返回请求统一下单的XML
	 * @param body
	 * @param out_trade_no
	 * @param total_fee
	 * @param spbill_create_ip
	 * @param notify_url
	 * @param openid
	 * @param nonce_str
	 * @param sign
	 * @return
	 * @throws Exception
	 */
	private StringBuffer returnRequestContent(String body,String out_trade_no,
			String total_fee,String spbill_create_ip,String notify_url,String openid,String nonce_str,String sign,String attach) throws Exception
	{
		//构成统一下单接口XML结构内容
		StringBuffer requestContent= new StringBuffer();
		requestContent.append("<xml>");
		requestContent.append("<appid>"+APPID+"</appid>");
		requestContent.append("<attach>"+attach+"</attach>");
		requestContent.append("<mch_id>"+MCH_ID+"</mch_id>");
		requestContent.append("<nonce_str>"+nonce_str+"</nonce_str>");
		requestContent.append("<sign>"+sign+"</sign>");
		requestContent.append("<body>"+body+"</body>");
		requestContent.append("<out_trade_no>"+out_trade_no+"</out_trade_no>");
		requestContent.append("<fee_type>"+FEE_TYPE+"</fee_type>");
		requestContent.append("<total_fee>"+total_fee+"</total_fee>");
		requestContent.append("<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>");
		requestContent.append("<notify_url>"+notify_url+"</notify_url>");
		requestContent.append("<trade_type>"+TRADE_TYPE+"</trade_type>");
		requestContent.append("<openid>"+openid+"</openid>");
		requestContent.append("</xml>");
		return requestContent;
	}
	
	/**
	 * 统一下单签名
	 * @param appid
	 * @param mch_id
	 * @param nonce_str
	 * @param body
	 * @param out_trade_no
	 * @param fee_type
	 * @param total_fee
	 * @param spbill_create_ip
	 * @param notify_url
	 * @param trade_type
	 * @param openid
	 * @param attach
	 * @return
	 * @throws Exception
	 */
	private String returnSignMd5(String appid,String mch_id,String nonce_str,String body,String out_trade_no,
			String fee_type,String total_fee,String spbill_create_ip,String notify_url,
			String trade_type,String openid,String attach) throws Exception
	{
		//step1-----拼接字符串，key value 形式
		appid="appid="+appid;
		mch_id="mch_id="+mch_id;
		nonce_str="nonce_str="+nonce_str;
		body="body="+body;
		out_trade_no="out_trade_no="+out_trade_no;
		fee_type="fee_type="+fee_type;
		total_fee="total_fee="+total_fee;
		spbill_create_ip="spbill_create_ip="+spbill_create_ip;
		notify_url="notify_url="+notify_url;
		trade_type="trade_type="+trade_type;
		openid="openid="+openid;
		attach="attach="+attach;
		
		String[] arr = new String[] {appid, mch_id, nonce_str,body,out_trade_no,fee_type,
				total_fee,spbill_create_ip,notify_url,trade_type,openid,attach};
		//step2-----将参数进行字典排序
		Arrays.sort(arr);
		StringBuilder content = new StringBuilder();
		for (int i = 0; i < arr.length; i++) {
			content.append(arr[i]+"&");
		}
		//step3-----将 key=xxx 加入最末位
		String ss = content+"key="+KEY;
//		System.out.println("ss----"+ss);
		//step4-----将拼接号的字符串，MD5加密32位
		String sign_md5 = MD5Security.md5(ss);
		//System.out.println("sign----"+sign_md5);
		return sign_md5.toUpperCase();
	}
	
	public static void main(String[] args) throws Exception
	{
		//JSAPI paySign
		String paySign = getJSAPIpaySign(APPID, "da313bf15ada43238e889da98c4a7dc4", "wx20161009170615602352e6890329335068", SIGNTYPE,"");
		System.out.println(paySign);
		
		/*String requestContent="<xml>"
				+ "<return_code>SUCCESS]]></return_code>"
				+ "<return_msg><![CDATA[OK]]></return_msg>"
				+ "<appid><![CDATA[wx2421b1c4370ec43b]]></appid>"
				+ "<mch_id><![CDATA[10000100]]></mch_id>"
				+ "<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>"
				+ "<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>"
				+ "<result_code><![CDATA[SUCCESS]]></result_code>"
				+ "<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>"
				+ "<trade_type><![CDATA[JSAPI]]></trade_type>"
				+ "</xml>";
		Map resultMap = returnPrepayIdForXml(requestContent);
		
		String return_code = resultMap.get("return_code").toString();
		if(SUCCESS.equals(return_code)){
			System.out.println("prepay_id----"+resultMap.get("prepay_id").toString());
		}else{
			System.out.println("return_msg----"+resultMap.get("return_msg").toString());
		}
		
		System.out.println(resultMap.toString());*/
	}
}